home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / telecomm / wterm.arc / WTERMF.C < prev    next >
Encoding:
C/C++ Source or Header  |  1985-11-20  |  23.5 KB  |  787 lines

  1. /*
  2.  * WTERMF - Window Terminal, 'full' version
  3.  *
  4.  * Matt Kimmel, 1987
  5.  *
  6.  * This program implements a terminal program inside a window as a desk
  7.  * accessory.  See the header in the 'stripped' version for programming
  8.  * notes.
  9.  *
  10.  * This version is larger and slower but contains many features - three
  11.  * font sizes, RS232 buffer sizing, a cursor, setting of RS232 parameters,
  12.  * and saving of configuration.  This version requires a resource file,
  13.  * WTERMF.C.
  14.  *
  15.  */
  16. #include <stdio.h>
  17. #include <gemdefs.h>
  18. #include <osbind.h>
  19. #include <obdefs.h>
  20. #include <string.h>
  21. #include "wtermf.h" /* Resource defs */
  22.  
  23. /* Defines for window gadgets */
  24. #define NAME 0x0001
  25. #define CLOSE 0x0002
  26. #define FULL 0x0004
  27. #define MOVE 0x0008
  28. #define SIZE 0x0020
  29. /* Macros to turn mouse pointer on and off */
  30. #define MOUSE_ON graf_mouse(257,&j)
  31. #define MOUSE_OFF graf_mouse(256,&j)
  32.  
  33. /* Structure for iorec() */
  34. typedef struct {
  35.   char *ibuf;
  36.   int ibufsiz;
  37.   int ibufhd;
  38.   int ibuftl;
  39.   int ibuflow;
  40.   int ibufhi;
  41.   } IORECORD;
  42.  
  43. /* VDI variables - why aren't these in a header file? */
  44. int contrl[12], intin[128],ptsin[128],intout[128],ptsout[128];
  45. int w_handle, handle, workin[11], workout[57];
  46. int x,y,w,h; /* Current coordinates of window */
  47. int j;
  48. int nx, ny; /* coordinates of next character to be output */
  49. int tx, ty, tw, th; /* Work area of window */
  50. int hsize, vsize; /* Horizontal and vertical size of characters */
  51. int apid, menuid;
  52. OBJECT *mainmenu, *setrs, *setfont, *rsize;
  53. int baud, ucr, flow, cursor, point, buffer_size; /* Various parameters */
  54. char *rb; /* Pointer to our RS232 buffer */
  55. char strsiz[10];
  56. char aboutstr[] = "[1][Window Term 1.0|Full Version|by Matt Kimmel, 1987][OK]";
  57.  
  58. main()
  59. {
  60.   int j;
  61.   int msg[8];
  62.   FILE *conf;
  63.   int dx,dy,dw,dh; /* Desktop work area */
  64.  
  65.   apid = appl_init();
  66.   if (!rsrc_load("WTERMF.RSC"))
  67.     for(;;)
  68.       evnt_mesag(msg); /* If we can't open the resource file, we'll
  69.                           just sit here and release the system to
  70.                           the time slicer */
  71.   rsrc_gaddr(0,MENU,&mainmenu);
  72.   rsrc_gaddr(0,RS232,&setrs);
  73.   rsrc_gaddr(0,FONT,&setfont);
  74.   rsrc_gaddr(0,BUFSET,&rsize);
  75.   ((TEDINFO *)rsize[BSIZ].ob_spec)->te_ptext = strsiz;
  76.   if ((conf = fopen("\WTERMF.INF","r")) == NULL) {
  77.     /* If we can't open the config file, set up the defaults */
  78.     baud = 7; /* 1200 baud */
  79.     ucr = 136; /* 8,N,1 */
  80.     flow = 0; /* no flow control */
  81.     cursor = 1; /* cursor on */
  82.     point = ((Getrez() == 2)?(10):(9)); /* normal font for this resolution */
  83.     buffer_size = 8192; /* 8K RS232 buffer */
  84.     /* default window coordinates */
  85.     x=50;
  86.     y=50;
  87.     w=200;
  88.     h=100;
  89.     }
  90.   else {
  91.     /* Get parameters from the config file */
  92.     fscanf(conf,"%d",&baud);
  93.     fscanf(conf,"%d",&ucr);
  94.     fscanf(conf,"%d",&flow);
  95.     fscanf(conf,"%d",&cursor);
  96.     fscanf(conf,"%d",&point);
  97.     fscanf(conf,"%d",&buffer_size);
  98.     fscanf(conf,"%d",&x);
  99.     fscanf(conf,"%d",&y);
  100.     fscanf(conf,"%d",&w);
  101.     fscanf(conf,"%d",&h);
  102.     fclose(conf);
  103.     }
  104.   wind_get(0,WF_WORKXYWH,&dx,&dy,&dw,&dh); /* Get work area of desktop */
  105.   /* Fix window coordinates if necessary to fit inside desktop */
  106.   if ((x < dx) || (x > (dx + dw))) x=dx;
  107.   if ((y < dy) || (y > (dy+dh))) y=dy;
  108.   if ((x + w) > (dx + dw)) w=((dx + dw) - x) - 8;
  109.   if ((y + h) > (dy + dh)) h=((dy + dh) - x);
  110.   /* Align window to be byte-aligned in screen RAM */
  111.   align8(&x,&y,&w,&h);
  112.   init_buttons(); /* Set up buttons in dialog boxes */
  113.   if ((point == 10) && (Getrez() != 2)) point = 9; /* Fix font for color */
  114.   Rsconf(baud,flow,ucr,-1,-1,-1);
  115.   menuid = menu_register(apid,"  Window Terminal");
  116.   handle = graf_handle(&j,&j,&j,&j);
  117.   for(j=0;j++<=9;workin[j]=1);
  118.   workin[10] = 2;
  119.   v_opnvwk(workin,&handle,workout);
  120.   vst_alignment(handle,0,5,&j,&j);
  121.   vst_point(handle,point,&j,&j,&hsize,&vsize);
  122.   vst_color(handle,1);
  123.   vsl_color(handle,1);
  124.   vswr_mode(handle,1);
  125.   /* Allocate new RS232 buffer.  calloc() is used because it zeroes the
  126.      memory it allocates */
  127.   rb = calloc(buffer_size,sizeof(char));
  128.   /* If we can't allocate the memory, hang */
  129.   if (rb == NULL)
  130.     for (;;)
  131.       evnt_mesag(msg);
  132.   set_rsbuf();
  133.   for (;;) {
  134.     evnt_mesag(msg);  /* Wait around to be selected */
  135.     if (msg[0] == AC_OPEN)
  136.       acc();
  137.     }
  138. }
  139.  
  140. /*
  141.  * This is the main accessory - it handles messages and i/o.
  142.  */
  143. acc()
  144. {
  145.   int msg[8], d, which;
  146.   int i;
  147.   int a, j;
  148.   int desel = 0; /* Is the window deselected? */
  149.   int dx,dy,dw,dh;
  150.   int stopped = 0; /* Has the window been stopped with ALT-S? */
  151.   long l;
  152.   int p[4];
  153.  
  154.   if (init_window() == 0) return; /*If we can't allocate a window, forget it*/
  155.   align8(&x,&y,&w,&h);
  156.   graf_growbox(24,0,56,16,x,y,w,h);
  157.   wind_open(w_handle,x,y,w,h); /* Open our window */
  158.   wind_get(w_handle,WF_WORKXYWH,&tx,&ty,&tw,&th); /* Get its work area */
  159.   clr(); /* clear it */
  160.   Cauxout(17); /* Send a CTRL-Q, just in case */
  161.   for(;;) {
  162.     /* Release time to the time slicer, but come back every (theoretically)
  163.        0 milliseconds.  Also wait for messages. */
  164.     which = evnt_multi(MU_MESAG|MU_TIMER,0,0,0,0,0,0,0,0,0,0,0,0,0,
  165.                        msg,0,0,&d,&d,&d,&d,&d,&d);
  166.     /* See if our window is still on top */
  167.     wind_get(w_handle,WF_TOP,&a,&j,&j,&j);
  168.     if ((a != w_handle) && (desel == 0)) {   /* Window has been deselected */
  169.       if (stopped != 1) Cauxout(19); /* Send a CTRL-S if the window isn't
  170.                                         stopped */
  171.       desel = 1;
  172.       }
  173.     else
  174.       if ((a == w_handle) && (desel == 1)) { /* Window has been selected */
  175.         if (stopped != 1) Cauxout(17); /* Send a CTRL-Q, if window isn't
  176.                                           stopped */
  177.         desel = 0;
  178.         }
  179.     /* If there are no messages and our window is on top, do some i/o */
  180.     if ((which & MU_TIMER) && (a == w_handle)) {
  181.       /* If there's a character waiting at the keyboard, get it */
  182.       if (Bconstat(2)) {
  183.         l = Bconin(2);
  184.         if (l == 2031616L) /* Is it ALT-S? */
  185.           if (stopped == 0) { /* Yes, toggle stopped window */
  186.             Cauxout(19);
  187.             stopped = 1;
  188.             }
  189.           else {
  190.             Cauxout(17);
  191.             stopped = 0;
  192.             }
  193.         Cauxout((int)l); /* Output the character to RS232.  If it was ALT-S,
  194.                             a 0 will be output */
  195.         }
  196.       /* If there's a character waiting at the RS232 port, and the
  197.          window is not stopped, output it. */
  198.       if (Cauxis() && (stopped == 0)) {
  199.         i = Cauxin();
  200.         MOUSE_OFF; /* turn off mouse */
  201.         if (cursor) { /* erase cursor */
  202.           p[0] = (nx + (hsize / 2));
  203.           p[1] = (ny - 1);
  204.           p[2] = p[0];
  205.           p[3] = ((ny + vsize) + 1);
  206.           vswr_mode(handle,3);
  207.           v_pline(handle,2,p);
  208.           vswr_mode(handle,1);
  209.           }
  210.         outchar(i); /* output the character */
  211.         if (cursor) { /* draw the cursor */
  212.           p[0] = (nx + (hsize / 2));
  213.           p[1] = (ny - 1);
  214.           p[2] = p[0];
  215.           p[3] = ((ny + vsize) + 1);
  216.           vswr_mode(handle,3);
  217.           v_pline(handle,2,p);
  218.           vswr_mode(handle,1);
  219.           }
  220.         MOUSE_ON; /* turn on the mouse */
  221.         }
  222.       }
  223.     if (which & MU_MESAG) {
  224.       switch(msg[0]) {
  225.         case WM_REDRAW : redraw(); /* redraw window and reset character */
  226.                          nx=tx;    /* coordinates                       */
  227.                          ny=ty;
  228.                          break;
  229.         case WM_NEWTOP : /* put appropriate window on top */
  230.         case WM_TOPPED : wind_set(w_handle,WF_TOP,msg[3],0,0,0);
  231.                          clr();
  232.                          break;
  233.         case AC_OPEN   : do_menu(); /* Let the user select a command */
  234.                          break;
  235.         case AC_CLOSE  : return; /* Our window has been closed and deleted */
  236.                          break;  /* for us.                                */
  237.         case WM_CLOSED : wind_close(w_handle); /* close and delete window */
  238.                          graf_shrinkbox(24,0,56,16,x,y,w,h);
  239.                          wind_delete(w_handle);
  240.                          return; /* exit */
  241.                          break;
  242.         case WM_FULLED : full_window();
  243.                          break;
  244.         case WM_MOVED  : wind_get(0,WF_WORKXYWH,&dx,&dy,&dw,&dh);
  245.                          /* Fix window to be inside the desktop */
  246.                          if (((msg[4] + msg[6]) - 1) > ((dx + dw) - 1))
  247.                            msg[4] = ((dx + dw) - 1) - msg[6];
  248.                          if (((msg[5] + msg[7]) - 1) > ((dy + dh) - 1))
  249.                            msg[5] = ((dy + dh) - 1) - msg[7];
  250.                          align8(&msg[4],&msg[5],&msg[6],&msg[7]);
  251.                          nx += (msg[4] - x); /* Cursor will be at the same */
  252.                          ny += (msg[5] - y); /* position relative to the   */
  253.                          x=msg[4];           /* window                     */
  254.                          y=msg[5];
  255.                          w=msg[6];
  256.                          h=msg[7];
  257.                          wind_set(w_handle,WF_CURRXYWH,x,y,w,h);
  258.                          wind_get(w_handle,WF_WORKXYWH,&tx,&ty,&tw,&th);
  259.                          break;
  260.         case WM_SIZED  : x=msg[4]; /* Size window and align it */
  261.                          y=msg[5];
  262.                          w=msg[6];
  263.                          h=msg[7];
  264.                          align8(&x,&y,&w,&h);
  265.                          wind_set(w_handle,WF_CURRXYWH,x,y,w,h);
  266.                          wind_get(w_handle,WF_WORKXYWH,&tx,&ty,&tw,&th);
  267.                          clr();
  268.                          break;
  269.         }
  270.       continue;
  271.       }
  272.     }
  273. }
  274.  
  275. /*
  276.  * this functions fulfills a redraw request.  It redraws ALL exposed
  277.  * portions of the window rather than just the 'dirty' rectangles.
  278.  */
  279. redraw()
  280. {
  281.   int lx,ly,lw,lh;
  282.   int pxy[4];
  283.   int active;
  284.   int j;
  285.  
  286.   /* if our window is on top, just use the clr() function.  It's faster. */
  287.   wind_get(w_handle,WF_TOP,&active,&j,&j,&j);
  288.   if (active == w_handle) {
  289.     clr();
  290.     return;
  291.     }
  292.   vsf_interior(handle,0);
  293.   MOUSE_OFF; /* turn off mouse */
  294.   wind_update(BEG_UPDATE); /* Begin update - don't let GEM change anything */
  295.   /* Get rectangles one by one and fill them in.  Fill ALL exposed portions
  296.      of the window. */
  297.   wind_get(w_handle,WF_FIRSTXYWH,&lx,&ly,&lw,&lh);
  298.   while (lw && lh) {
  299.     pxy[0] = lx;
  300.     pxy[1] = ly;
  301.     pxy[2] = (lx + lw) - 1;
  302.     pxy[3] = (ly + lh) - 1;
  303.     vr_recfl(handle,pxy);
  304.     wind_get(w_handle,WF_NEXTXYWH,&lx,&ly,&lw,&lh);
  305.     }
  306.   wind_update(END_UPDATE); /* End our update; let GEM change things again */
  307.   MOUSE_ON; /* turn on mouse */
  308. }
  309.  
  310. /*
  311.  * clear the window if it's on top.
  312.  */
  313. clr()
  314. {
  315.   int active;
  316.   int j;
  317.   int p[4];
  318.  
  319.   /* Don't do anything if our window is not on top. */
  320.   wind_get(w_handle,WF_TOP,&active,&j,&j,&j);
  321.   if (active == w_handle) {
  322.     wind_get(w_handle,WF_WORKXYWH,&p[0],&p[1],&p[2],&p[3]); /* get work area */
  323.     p[2] += (p[0] - 1); /* Fix w and h to be x2 and y2 */
  324.     p[3] += (p[1] - 1);
  325.     vsf_interior(handle,0);
  326.     MOUSE_OFF;    
  327.     vr_recfl(handle,p); /* Wipe window */
  328.     nx=tx; /* Reset character coordinates */
  329.     ny=ty;
  330.     /* Draw the cursor if necessary */
  331.     if (cursor) {
  332.       p[0] = (nx + (hsize / 2));
  333.       p[1] = (ny - 1);
  334.       p[2] = p[0];
  335.       p[3] = ((ny + vsize) + 1);
  336.       vswr_mode(handle,1);
  337.       v_pline(handle,2,p);
  338.       }
  339.     MOUSE_ON;
  340.     }
  341. }
  342.  
  343. /*
  344.  * Make sure that the window's work area is byte-aligned.  this speeds
  345.  * up scrolling with vro_cpyfm().
  346.  */
  347. align8(fx,fy,fw,fh)
  348. int *fx,*fy,*fw,*fh;
  349. {
  350.   int ix,iy,iw,ih;
  351.   
  352.   /* This returns coordinates for the entire window, not just the work
  353.      area, so we need to convert coordinates back and forth with
  354.      wind_calc(). */
  355.   wind_calc(1,NAME|CLOSE|FULL|MOVE|SIZE,*fx,*fy,*fw,*fh,&ix,&iy,&iw,&ih);
  356.   while ((ix % 8) != 0)
  357.     ix++;
  358.   while ((iw % 8) != 0)
  359.     iw++;
  360.   wind_calc(0,NAME|CLOSE|FULL|MOVE|SIZE,ix,iy,iw,ih,fx,fy,fw,fh);
  361. }
  362.  
  363. /*
  364.  * fulfill a full_window() request.
  365.  */
  366. full_window()
  367. {
  368.   int jx,jy,jw,jh,fx,fy,fw,fh;
  369.   
  370.   /* get 'full size'.  This is already byte-aligned. */
  371.   wind_get(w_handle,WF_FULLXYWH,&fx,&fy,&fw,&fh);
  372.   /* if the window is already full, unfull it. */
  373.   if ((x == fx) && (y == fy) && (w == fw) && (h == fh)) {
  374.     wind_get(w_handle,WF_PREVXYWH,&jx,&jy,&jw,&jh);
  375.     graf_shrinkbox(jx,jy,jw,jh,x,y,w,h);
  376.     x=jx;
  377.     y=jy;
  378.     w=jw;
  379.     h=jh;
  380.     wind_set(w_handle,WF_CURRXYWH,x,y,w,h);
  381.     wind_get(w_handle,WF_WORKXYWH,&tx,&ty,&tw,&th);
  382.     nx=tx;
  383.     ny=ty;
  384.     }
  385.   else { /* full the window */
  386.     wind_get(w_handle,WF_FULLXYWH,&jx,&jy,&jw,&jh);
  387.     graf_growbox(x,y,w,h,jx,jy,jw,jh);
  388.     x=jx;
  389.     y=jy;
  390.     w=jw;
  391.     h=jh;
  392.     wind_set(w_handle,WF_CURRXYWH,x,y,w,h);
  393.     wind_get(w_handle,WF_WORKXYWH,&tx,&ty,&tw,&th);
  394.     nx=tx;
  395.     ny=ty;
  396.     }
  397.   clr();
  398. }
  399.  
  400. /*
  401.  * initialize and allocate the window
  402.  */
  403. init_window()
  404. {
  405.   int bx,by,bw,bh;
  406.   
  407.   wind_get(0,WF_WORKXYWH,&bx,&by,&bw,&bh); /* set up FULLXYWH value */
  408.   align8(&bx,&by,&bw,&bh);
  409.   bw -= 8;
  410.   w_handle = wind_create(NAME|CLOSE|FULL|MOVE|SIZE,bx,by,bw,bh);
  411.   if (w_handle < 0) { /* If we can't allocate a window, apologize */
  412.     form_alert(1,"[3][There are no more|windows available!][Sorry!]");
  413.     return (0);
  414.     }
  415.   wind_set(w_handle,WF_NAME," Window Term 1.0-F ",0,0);
  416.   return(1);
  417. }
  418.  
  419. /*
  420.  * Install our new RS232 buffer
  421.  */
  422. set_rsbuf()
  423. {
  424.   IORECORD *b;
  425.  
  426.   Cauxout(19); /* We don't want incoming characters during this */
  427.   b = (IORECORD *)Iorec(0); /* make our structure point to the RS232 struct */
  428.   b->ibuf = rb; /* fill it in! */
  429.   b->ibufsiz = buffer_size;
  430.   b->ibuflow = buffer_size/4;
  431.   b->ibufhi = buffer_size/4*3;
  432.   b->ibufhd = 0;
  433.   b->ibuftl = 0;
  434.   Cauxout(17); /* Send a CTRL-Q */
  435. }
  436.  
  437. /*
  438.  * Set up the buttons on the dialog boxes
  439.  */
  440. init_buttons()
  441. {
  442.   int j;
  443.   char foo[10];
  444.  
  445.   /* Clear all the buttons */
  446.   for (j=0;j<=32;j++)
  447.     if (((setrs[j].ob_type) == G_BUTTON)||((setrs[j].ob_type) == G_BOXCHAR)) {
  448.       setrs[j].ob_state &= (~SELECTED);
  449.       setrs[j].ob_state |= NORMAL;
  450.       }
  451.   for (j=0;j<=7;j++)
  452.     if ((setfont[j].ob_type) == G_BUTTON) {
  453.       setfont[j].ob_state &= (~SELECTED);
  454.       setfont[j].ob_state |= NORMAL;
  455.       }
  456.   /* Set appropriate buttons */
  457.   if (baud == 0) objc_change(setrs,B19200,0,0,0,0,0,SELECTED,0);
  458.   if (baud == 1) objc_change(setrs,B9600,0,0,0,0,0,SELECTED,0);
  459.   if (baud == 2) objc_change(setrs,B4800,0,0,0,0,0,SELECTED,0);
  460.   if (baud == 4) objc_change(setrs,B2400,0,0,0,0,0,SELECTED,0);
  461.   if (baud == 7) objc_change(setrs,B1200,0,0,0,0,0,SELECTED,0);
  462.   if (baud == 9) objc_change(setrs,B300,0,0,0,0,0,SELECTED,0);
  463.   if (flow == 0) objc_change(setrs,FLOWNONE,0,0,0,0,0,SELECTED,0);
  464.   if (flow == 1) objc_change(setrs,FLOWXON,0,0,0,0,0,SELECTED,0);
  465.   if (flow == 2) objc_change(setrs,FLOWRTS,0,0,0,0,0,SELECTED,0);
  466.   if (flow == 3) objc_change(setrs,FLOWBOTH,0,0,0,0,0,SELECTED,0);
  467.   if ((ucr & 4) && (ucr & 2))
  468.     objc_change(setrs,EVEN,0,0,0,0,0,SELECTED,0);
  469.   if ((ucr & 4) && (!(ucr & 2)))
  470.     objc_change(setrs,ODD,0,0,0,0,0,SELECTED,0);
  471.   if (!(ucr & 4))
  472.     objc_change(setrs,NONE,0,0,0,0,0,SELECTED,0);
  473.   if ((!(ucr & 16)) && (ucr & 8))
  474.     objc_change(setrs,STOP1,0,0,0,0,0,SELECTED,0);
  475.   if ((ucr & 16) && (ucr & 8))
  476.     objc_change(setrs,STOP2,0,0,0,0,0,SELECTED,0);
  477.   if ((!(ucr & 64)) && (!(ucr & 32)))
  478.     objc_change(setrs,BIT8,0,0,0,0,0,SELECTED,0);
  479.   if ((!(ucr & 64)) && (ucr & 32))
  480.     objc_change(setrs,BIT7,0,0,0,0,0,SELECTED,0);
  481.   if ((ucr & 64) && (!(ucr & 32)))
  482.     objc_change(setrs,BIT6,0,0,0,0,0,SELECTED,0);
  483.   if ((ucr & 64) && (ucr & 32))
  484.     objc_change(setrs,BIT5,0,0,0,0,0,SELECTED,0);
  485.   if ((point == 10) && (Getrez() != 2))
  486.     objc_change(setfont,COLOR,0,0,0,0,0,SELECTED,0);
  487.   else
  488.     if (point == 10)
  489.       objc_change(setfont,MONO,0,0,0,0,0,SELECTED,0);
  490.   if (point == 9)
  491.     objc_change(setfont,COLOR,0,0,0,0,0,SELECTED,0);
  492.   if (point == 8)
  493.     objc_change(setfont,ICON,0,0,0,0,0,SELECTED,0);
  494.   if (Getrez() != 2)
  495.     objc_change(setfont,MONO,0,0,0,0,0,DISABLED,0);
  496.   sprintf(strsiz,"%d",buffer_size);
  497. }
  498.  
  499. /*
  500.  * Do main dialog; allow user to select a command
  501.  */
  502. do_menu()
  503. {
  504.   int which;
  505.   int dx,dy,dw,dh;
  506.  
  507.   evnt_timer(0,0);         /* Lots of stuff to make sure dialogs aren't */
  508.   wind_update(BEG_UPDATE); /* redrawn over by other applications */
  509.   form_center(mainmenu,&dx,&dy,&dw,&dh);
  510.   form_dial(FMD_START,dx,dy,dw,dh,dx,dy,dw,dh);
  511.   objc_draw(mainmenu,0,10,dx,dy,dw,dh);
  512.   which = form_do(mainmenu,0);
  513.   objc_change(mainmenu,which,0,0,0,0,0,NORMAL,0);
  514.   wind_update(END_UPDATE);
  515.   form_dial(FMD_FINISH,dx,dy,dw,dh,dx,dy,dw,dh);
  516.   switch(which) {
  517.     case SETRS232 : set_rs232();
  518.                     break;
  519.     case BUFSIZE  : size_buffer();
  520.                     break;
  521.     case SETSIZE  : set_charsize();
  522.                     break;
  523.     case CURSON   : cursor = ((cursor == 1)?(0):(1));
  524.                     clr();
  525.                     break;
  526.     case SAVESET  : save_settings();
  527.                     break;
  528.     case ABOUT    : form_alert(1,aboutstr);
  529.                     break;
  530.     }
  531. }
  532.  
  533. /*
  534.  * Let user set RS232 parameters
  535.  */
  536. set_rs232()
  537. {
  538.   int which;
  539.   int dx,dy,dw,dh;
  540.  
  541.   /* Do the dialog ... */
  542.   evnt_timer(0,0);
  543.   wind_update(BEG_UPDATE);
  544.   form_center(setrs,&dx,&dy,&dw,&dh);
  545.   form_dial(FMD_START,dx,dy,dw,dh,dx,dy,dw,dh);
  546.   objc_draw(setrs,0,10,dx,dy,dw,dh);
  547.   which = form_do(setrs,0);
  548.   objc_change(setrs,which,0,0,0,0,0,NORMAL,0);
  549.   wind_update(END_UPDATE);
  550.   form_dial(FMD_FINISH,dx,dy,dw,dh,dx,dy,dw,dh);
  551.   if (which == RCANCEL) {
  552.     init_buttons();
  553.     return;
  554.     }
  555.   /* ... and set the parameters accordingly */
  556.   if (sel(setrs,B19200)) baud = 0;
  557.   if (sel(setrs,B9600)) baud = 1;
  558.   if (sel(setrs,B4800)) baud = 2;
  559.   if (sel(setrs,B2400)) baud = 4;
  560.   if (sel(setrs,B1200)) baud = 7;
  561.   if (sel(setrs,B300)) baud = 9;
  562.   if (sel(setrs,FLOWNONE)) flow = 0;
  563.   if (sel(setrs,FLOWXON)) flow = 1;
  564.   if (sel(setrs,FLOWRTS)) flow = 2;
  565.   if (sel(setrs,FLOWBOTH)) flow = 3;
  566.   ucr = 0;
  567.   if (sel(setrs,EVEN)) ucr |= 6;
  568.   if (sel(setrs,ODD)) ucr |= 4;
  569.   if (sel(setrs,STOP1)) ucr |= 8;
  570.   if (sel(setrs,STOP2)) ucr |= 24;
  571.   if (sel(setrs,BIT7)) ucr |= 32;
  572.   if (sel(setrs,BIT6)) ucr |= 64;
  573.   if (sel(setrs,BIT5)) ucr |= 96;
  574.   ucr |= 128;
  575.   Rsconf(baud,flow,ucr,-1,-1,-1);
  576. }
  577.  
  578. /*
  579.  * Let the user size the RS232 buffer
  580.  */
  581. size_buffer()
  582. {
  583.   int dx,dy,dw,dh,which;
  584.   int oldbuf;
  585.  
  586.   /* Do the dialog */
  587.   evnt_timer(0,0);
  588.   wind_update(BEG_UPDATE);
  589.   form_center(rsize,&dx,&dy,&dw,&dh);
  590.   form_dial(FMD_START,dx,dy,dw,dh,dx,dy,dw,dh);
  591.   objc_draw(rsize,0,10,dx,dy,dw,dh);
  592.   which = form_do(rsize,BSIZ);
  593.   objc_change(rsize,which,0,0,0,0,0,NORMAL,0);
  594.   wind_update(END_UPDATE);
  595.   form_dial(FMD_FINISH,dx,dy,dw,dh,dx,dy,dw,dh);
  596.   if (which == BCANCEL) {
  597.     init_buttons();
  598.     return;
  599.     }
  600.   /* set size */
  601.   oldbuf = buffer_size; /* save old buffer size */
  602.   buffer_size = atoi(strsiz); /* get new one */
  603.   free(rb); /* free the old memory */
  604.   rb = calloc(buffer_size,sizeof(char)); /* allocate the new */
  605.   if (rb == NULL) { /* if bad, generally bomb out. */
  606.     form_alert(1,"[3][Not enough memory|for a buffer of|that size.][Cancel]");
  607.     buffer_size = oldbuf;
  608.     rb = calloc(buffer_size,sizeof(char)); /* reallocate the old buffer. We
  609.                                               don't have any error-checking
  610.                                               here because if this fails,
  611.                                               we're in big trouble anyway */
  612.     init_buttons();
  613.     return;
  614.     }
  615.   set_rsbuf();
  616. }
  617.  
  618. /*
  619.  * Let user set the font (Mono, color, icon)
  620.  */
  621. set_charsize()
  622. {
  623.   int dx,dy,dw,dh,which,j;
  624.  
  625.   evnt_timer(0,0);
  626.   wind_update(BEG_UPDATE);
  627.   form_center(setfont,&dx,&dy,&dw,&dh);
  628.   form_dial(FMD_START,dx,dy,dw,dh,dx,dy,dw,dh);
  629.   objc_draw(setfont,0,10,dx,dy,dw,dh);
  630.   which = form_do(setfont,0);
  631.   objc_change(setfont,which,0,0,0,0,0,NORMAL,0);
  632.   wind_update(END_UPDATE);
  633.   form_dial(FMD_FINISH,dx,dy,dw,dh,dx,dy,dw,dh);
  634.   if (which == FCANCEL) {
  635.     init_buttons();
  636.     return;
  637.     }
  638.   if (sel(setfont,MONO)) point = 10;
  639.   if (sel(setfont,COLOR)) point = 9;
  640.   if (sel(setfont,ICON)) point = 8;
  641.   vst_point(handle,point,&j,&j,&hsize,&vsize);
  642.   clr();
  643. }
  644.  
  645. /*
  646.  * save the configuration
  647.  */
  648. save_settings()
  649. {
  650.   int j;
  651.   FILE *fd;
  652.  
  653.   if ((fd = fopen("\WTERMF.INF","w")) == NULL) {
  654.     form_alert(1,"[3][Couldn't open|\WTERMF.INF\for writing.][Cancel]");
  655.     return;
  656.     }
  657.   graf_mouse(2,&j); /* "busy as a bee " */
  658.   fprintf(fd,"%d\n",baud);
  659.   fprintf(fd,"%d\n",ucr);
  660.   fprintf(fd,"%d\n",flow);
  661.   fprintf(fd,"%d\n",cursor);
  662.   fprintf(fd,"%d\n",point);
  663.   fprintf(fd,"%d\n",buffer_size);
  664.   fprintf(fd,"%d\n%d\n%d\n%d\n",x,y,w,h);
  665.   fclose(fd);
  666.   graf_mouse(0,&j);
  667. }
  668.  
  669. /*
  670.  * Return non-zero if obj in tree is selected
  671.  */
  672. sel(tree,obj)
  673. OBJECT *tree;
  674. int obj;
  675. {
  676.   if ((tree[obj].ob_state) & SELECTED)
  677.     return (1);
  678.   else
  679.     return (0);
  680. }
  681.  
  682. /*
  683.  * output a character to the window, and scroll if necessary.
  684.  * Why doesn't the ST have built-in scrolling and such for its
  685.  * windows?
  686.  */
  687. outchar(ch)
  688. int ch;
  689. {
  690.   char str[2];
  691.   int j;
  692.  
  693.   if (ch == 10) {    /* Linefeed */
  694.     if ((ny + vsize) > ((ty + th) - vsize)) { /* scroll if necessary */
  695.       scroll();
  696.       return;
  697.       }
  698.     ny += vsize;
  699.     return;
  700.     }
  701.   if (ch == 13) {    /* Carriage Return */
  702.     nx = tx;
  703.     return;
  704.     }
  705.   if (ch == 7)  {    /* Bell */
  706.     Bconout(2,7); /* ding! */
  707.     return;
  708.     }
  709.   if ((ch == 8) && (cursor)) { /* cursor is non-destructive if the cursor */
  710.     if (nx > tx)               /* is on.                                  */
  711.       nx -= hsize;
  712.     return;
  713.     }
  714.   if (ch == 9) {     /* Tab */
  715.     outchar(32);  /* faster than a for loop */
  716.     outchar(32);
  717.     outchar(32);
  718.     outchar(32);
  719.     outchar(32);
  720.     /* Tabs are 5 characters right now.  Perhaps in a later version I'll
  721.        let the user set the tab size. */
  722.     return;
  723.     }
  724.   if (ch == 12) {    /* Form Feed (clear screen) */
  725.     clr();
  726.     nx=tx;
  727.     ny=ty;
  728.     return;
  729.     }
  730.   if ((ch == 127) || ((ch == 8) && (!cursor))) {   /* DEL and Backspace */
  731.     if (nx > tx) {
  732.       nx -= hsize;
  733.       v_gtext(handle,nx,ny," ");
  734.       }
  735.     return;
  736.     }
  737.   str[0] = (char)ch;
  738.   str[1] = '\0';
  739.   v_gtext(handle,nx,ny,str); /* output the character */
  740.   nx += hsize;
  741.   if (nx > ((tx + tw) - hsize)) { /* wrap if necessary */
  742.     nx = tx;
  743.     if ((ny + vsize) > ((ty + th) - vsize)) scroll(); /* scroll if necessary */
  744.     else ny += vsize;
  745.     }
  746. }
  747.  
  748. /*
  749.  * This routine scrolls the window up one line.  This should be built into
  750.  * the ST - it took me quite a while to get this thing working.
  751.  * Basically what it does is copy all the lines but the top one up one
  752.  * line (as one block).  Then it wipes the bottom line clean.
  753.  */
  754. scroll()
  755. {
  756.   int pxy[4];
  757.   
  758.   blit(tx,(ty + vsize),((tx + tw) - 1),(((ty + vsize) + th) - (vsize + 1)),
  759.        tx,ty,((tx + tw) - 1),((ty + th) - (vsize + 1)));
  760.   pxy[0] = tx;
  761.   pxy[1] = ny;
  762.   pxy[2] = (tx + tw) - 1;
  763.   pxy[3] = ny + vsize;
  764.   vsf_interior(handle,0);
  765.   vr_recfl(handle,pxy);
  766. }
  767.  
  768. /*
  769.  * copy the block defined by x1, y1, x2, y2 to x3, y3, x4, y4
  770.  */
  771. blit(x1,y1,x2,y2,x3,y3,x4,y4)
  772. int x1,y1,x2,y2,x3,y3,x4,y4;
  773. {
  774.   FDB b;
  775.   int bp[8];
  776.   
  777.   bp[0] = x1;
  778.   bp[1] = y1;
  779.   bp[2] = x2;
  780.   bp[3] = y2;
  781.   bp[4] = x3;
  782.   bp[5] = y3;
  783.   bp[6] = x4;
  784.   bp[7] = y4;
  785.   vro_cpyfm(handle,3,bp,&b,&b); /* zap! */
  786. }
  787.